<?php
class CommonUtils{

	/**
	 * 获取DB Object
	 * @param $type int
	 * @return RecordObject
	 **/
	public static function getDbConn($type=0,$destination='db')
	{
		static $conn=array();
		static $target = array("reader","writer");
		static $class = array("ReadableRecordFactory","WritableRecordFactory");

		$config = ConfigReaderFactory::getInstance()->getConfigReader(AC::CONFIG_FILE)->getConfig();
		$db     = $config->$destination;
		$conn_name = $type.$destination;

		if(!isset($conn[$conn_name])){
			$conn[$conn_name] = new $class[$type] ($db->$target[$type],$db->user,(string)$db->pwd,$db->name);
		}
		return $conn[$conn_name];
	}

	/**
	 * for unit test
	 * 
	 * @param string $url : curl test url
	 * @param array  $fields : array("key1"=>value1,....);
	 **/
	public static function curl_test($url, $fields)
	{
		$cp = curl_init($url);
		curl_setopt($cp, CURLOPT_POST, 1 );
		if (!empty($fields))
		{
			curl_setopt($cp, CURLOPT_POSTFIELDS, $fields);
		}
		curl_setopt($cp,CURLOPT_RETURNTRANSFER,1);
		$ret = curl_exec($cp);
		$err_num = curl_errno($cp);
		if ($err_num > 0) return false;
		curl_close($cp);
		return $ret;
	}

	/**
	 * init folder
	 *
	 * @param varchar $object : such as programme,episode,cast and so on
	 */
	public static function init_folder($object, $action=null)
	{
		$folder = new folder();

		$init_meta = self::get_folder_config($object);

		if (!empty($init_meta))
		{
			$ids  = array();
			foreach ($init_meta as $value)
			{
				$folder->folder_type_id      = $value['id'];
				$folder->folder_item_type_id = $value['folder_item_type_id'];
				$folder->system_label = stripslashes(implode(' ',$value['name']));
				$folder->status = AC::STATUS_NEW;
				$folder->created_at = date("Y-m-d H:i:s");
				$folder->created_by = CommonUtils::get_user();
				$folder->modified_by = CommonUtils::get_user();
                $folder->modified_at = date("Y-m-d H:i:s");

				$ret = Model::$dbo['w']->save($folder);
				if ($ret > 0)
				{
					$ids[] = $ret;
					self::init_folder_language($ret, $value['name'], $action);
					if ($value['folder_item_type_id'] == AC::FOLDER_TYPE_IMAGE){
						Model::updateBySql(
							'insert into `image_folder-config`(folder_id,watermark_id)values(:fid,:wid)',
							array(':fid'=>$ret,':wid'=>array_search($value['watermark'], PDES_GD::$watermark))
						);

						if ($action) {
							$action->change_log[] = array(
								'type'=>'image_folder-config',
								'keys'=>array('folder_id'=>$ret),
								'is_active'=>1,
								'is_publish'=>0,
								'programme_id'=> & $action->_log_programme_id, // 在此處還不能知道最終的ID,務必在Action裏面填上
								'episode_id' => & $action->_log_episode_id, // 在此處還不能知道最終的ID,務必在Action裏面填上
							);
						}
					}

					if($action){
						$action->change_log[] = array(
							'type'=>'folder',
							'keys'=>array('id'=>$ret),
							'is_active'=>1,
							'is_publish'=>0,
							'programme_id'=> & $action->_log_programme_id, // 在此處還不能知道最終的ID,務必在Action裏面填上
							'episode_id' => & $action->_log_episode_id, // 在此處還不能知道最終的ID,務必在Action裏面填上
						);
						$action->addInfo("folder:create:".$ret, "add {$object}'s folder success", json_encode($folder));
					}
				}
				else
				{
					if($action){
						$action->addError("folder:create:".$ret, "add {$object}'s folder error", json_encode($folder));
					}
				}
			}
		}

		return implode(",", $ids);
	}

	/**
	 * create folder language data
	 */
	public function init_folder_language($id, $name, $action)
	{
		$folder_language = new folder_language();	

		foreach($name as $language=>$title){
			$language_id = $language=='cn' ? language::getLanguageID(AC::LANGUAGE_ZH) : language::getLanguageID(AC::LANGUAGE_EN);
			$folder_language->folder_id = $id;
			$folder_language->language_id = $language_id;
			$folder_language->title = stripslashes($title);

			$ret = Model::$dbo['w']->save($folder_language);
			if($action){
				if ($ret >= 0 )
				{
					$action->change_log[] = array(
						'type'=>'folder-language',
						'keys'=>array('folder_id'=>$id,'language_id'=>$language_id),
						'is_active'=>1,
						'is_publish'=>0,
						'programme_id'=> & $action->_log_programme_id, // 在此處還不能知道最終的ID,務必在Action裏面填上
						'episode_id' => & $action->_log_episode_id, // 在此處還不能知道最終的ID ,務必在Action裏面填上 
					);
					$action->addInfo("folder-language:".AC::LOG_OP_CREATE.":".$id, "add programme's folder language success", json_encode($folder_language));
				}
				else
				{
					$action->addError("folder-language:".AC::LOG_OP_CREATE.":".$id, "add programme's folder language error", json_encode($folder_language));
				}
			}
		}
	}

	/**
	 * get folder config from xml
	 * 
	 * @param varchar $object : such as programme,episode,cast and so on
	 *
	 * @return array
	 **/
	public function get_folder_config($object)
	{
		$xml = new Xml();

		$init_config = $xml->parse(AC::CONFIG_FOLDER_FILE, "FILE");

		$all_folders = $result = array();
		foreach($init_config['folders']['folder'] as $index=>$folder_name){
			$id = $init_config['folders']['folder-ATTR'][$index]['id'];
			$all_folders[$id] = array(
				'id'                  => $id,
				'folder_item_type_id' => $init_config['folders']['folder-ATTR'][$index]['item_type_id'],
				'name'                => array(
					'cn' => isset($folder_name['cn']) ? ($folder_name['cn']=='{{3}}' ? '' : $folder_name['cn']) : '',
					'en' => isset($folder_name['en']) ? ($folder_name['en']=='{{3}}' ? '' : $folder_name['en']) : ''
				)
			);
			if($all_folders[$id]['folder_item_type_id']==AC::FOLDER_TYPE_IMAGE){
				if(
					isset(   $init_config['folders']['folder-ATTR'][$index]['watermark']) 
				 && in_array($init_config['folders']['folder-ATTR'][$index]['watermark'], PDES_GD::$watermark)
				){
					$all_folders[$id]['watermark'] = $init_config['folders']['folder-ATTR'][$index]['watermark'];
				}else{
					$all_folders[$id]['watermark'] = PDES_GD::$watermark[0];
				}
			}
		}
		$init_folders = explode(',',$init_config[$object]['default_folders']);
		$init_folders = array_unique(array_filter($init_folders));
		foreach($init_folders as $folder_type_id){
			$result[] = $all_folders[$folder_type_id];
		}
		return $result;


		$init_meta   = $init_config[$object]['default_folders'];

		$sql = 'select id, folder_item_type_id, system_label as name from folder_type where id in (' . $init_meta .')';
		return Model::selectBySql($sql);

	}

	/**
	 * get allow tags from xml
	 *
	 * @param varchar $object : such as programme,episode and so on
	 *
	 * @return array
	 */
	public static function get_allow_tags($object)
	{
		$xml = new xml();
		$config = $xml->parse(AC::CONFIG_ALLOW_TAG, "FILE");
		return $config[$object];
	}

	/**
	 * get allow tags from xml
	 *
	 * @param varchar $object : such as programme,episode and so on
	 *
	 * @return array
	 */
	public static function get_highlight_role($object)
	{
		$xml = new xml();
		$config = $xml->parse(AC::CONFIG_HIIGHLIGHT_ROLE, "FILE");
		return $config[$object];
	}

	/**
	 * make url parameter by array
	 *
	 * @param array $arr : request's array
	 * @param array $filter : remain field
	 *
	 * @return string : for example a=1&b=2&c=3
	 */
	public static function make_url_parameter($arr, $filter)
	{
		$url = "";
		foreach ($arr as $key=>$value)
		{
			if (in_array($key,$filter)) 
				$url .=$key."=".$value."&";
		}

		return rtrim($url, "&");
	}

	/**
	 * Provisional data
	 */
	public static function get_user(){
		$userId = TVBGetAuthUserFromCookie();
		return (false == $userId) ? 'tvb' : $userId;
	}

	public static function get_user_group(){ return 'tvb-group'; }


	/**
	 * upload image to ii server
	 *
	 *    $result   = CommonUtils::upload_image_to_ii($_FILES['upload']);
	 *    $uploaded = ( array_sum($result['status']) == count($result['status']) );
	 *    if(!$uploaded) echo $result['error_msg'];
	 *
	 * @param String $source_file file_path
	 * @param Array $callback_args for ii callback api 
	 * @param Array $thumbnail [width],[height],[callback_args]
	 * @param Array $watermark [server_path],[width],[height],[callback_args] server_path:ii server watermark image file path
	 *
	 * @return Array(
	 *           'status'        => array('upload'=>0, 'thumbnail'=>1, 'watermark'=>1),
	 *           'source_id'     => '',
	 *           'source_url'    => '',
	 *           'resize_url'    => '',
	 *           'thumbnail_url' => '',
	 *           'error_msg'     => '',
	 *        )
	 */
	public static function upload_image_to_ii($source_file,array $callback_args=array(),$thumbnail=array(),array $watermark=array()){/*{{{*/
		$return = array(
			'status'        => array('upload'=>0, 'thumbnail'=>1, 'watermark'=>1),
			'source_id'     => '',
			'source_url'    => '',
			'resize_url'    => '',
			'thumbnail_url' => '',
			'error_msg'     => '',
			'ii_status'     => AC::IMAGE_STATUS_UPLOADED,
		);

		$uploader   = self::get_user();
		$image_info = getimagesize($source_file);
		if(!$image_info){
			$return['error_msg'] = "$source_file not is image file";
			return $return;
		}

		$ii = new ImageInfrastructureClient();
		$is = $ii->upload($uploader, $source_file);
		if(!is_object($is)){
			$return['error_msg'] = 'upload to II Server failure'."\n";
			$return['error_msg'].= "Call \$ii->upload($uploader,$source_file) failed, The method return '$is'! \n";
			return $return;
		}

		$return['status']['upload'] = 1;
		$return['source_id']        = $is->source_id;
		$return['source_url']       = $ii->GetSourceImageUrl($is->source_id);
		$return['resize_url']       = $return['source_url'];
		$return['thumbnail_url']    = $is->preview_url;

		$callback_url  = '';
		if($callback_args) $callback_url = AC::IMAGE_CALLBACK_API;

		// Thumbnail ===================
		if( isset($thumbnail['width']) || isset($thumbnail['height']) ){/*{{{*/
			if(isset($thumbnail['callback_args'])){
				if(is_array($thumbnail['callback_args'])) $callback_args = array_merge($callback_args, $thumbnail['callback_args']);
				else $callback_args['other_args'] = $thumbnail['callback_args'];
			}
			$export_id  = $ii->RequestExport(
				$uploader, 
				$is->source_id, 
				isset($thumbnail['width'])  ? $thumbnail['width']  : $image_info[0],
				isset($thumbnail['height']) ? $thumbnail['height'] : $image_info[1],
				AC::IMAGE_RESIZE_MODE, 
				'',
				AC::IMAGE_EXPORT_FORMAT, 
				'85',
				self::url_add_param($callback_url,$callback_args)
			);
			$return['thumbnail_url'] = self::getUrlFromIi($ii,$export_id,$is->preview_url,'thumbnail', $return);
		}/*}}}*/

		// Watermark ===================
		if( isset($watermark['server_path']) ){/*{{{*/
			if(isset($watermark['callback_args'])){
				if(is_array($watermark['callback_args'])) $callback_args = array_merge($callback_args, $watermark['callback_args']);
				else $callback_args['other_args'] = $watermark['callback_args'];
			}
			$export_id  = $ii->RequestExport(
				$uploader, 
				$is->source_id, 
				isset($watermark['width'])  ? $watermark['width']  : $image_info[0],
				isset($watermark['height']) ? $watermark['height'] : $image_info[1],
				AC::IMAGE_RESIZE_MODE, 
				$watermark['server_path'],
				AC::IMAGE_EXPORT_FORMAT, 
				'85',
				self::url_add_param($callback_url,$callback_args)
			);
			$return['resize_url'] = self::getUrlFromIi($ii,$export_id,$is->preview_url,'watermark', $return);
		}/*}}}*/

		return $return;
	}/*}}}*/

	/**
	 * get export image url
	 */
	public function getUrlFromIi($ii,$export_id,$old_url,$type,&$result){/*{{{*/
		$time_out   = AC::IMAGE_RESIZE_TIMEOUT * 1000000;
		$total_time = 0;

		$result['status'][$type] = AC::IMAGE_STATUS_UPLOADED;

		do{
			$total_time += 1000000/2;
			usleep(1000000/2);//1/2秒重試
			$url = $ii->getExportImageUrlEasily($export_id);
		}
		while($url=='2' && $total_time<$time_out);

		if($url == '-1'){	   // No export record found
			$result['status'][$type] = 0;
			$result['ii_status']     = AC::IMAGE_STATUS_FAILED;
			$result['error_msg']     = 'upload to II Server failure';
		}else if($url == '2'){ // Exporting
			$url = $old_url;
			$result['ii_status']     = AC::IMAGE_STATUS_WAITING;
		}else if($url == '0'){ // Waiting for distribution
			$result['ii_status']     = AC::IMAGE_STATUS_WAITING;
			$url = $old_url;
		}
		return $url;
	}/*}}}*/


	public static function url_add_param($url,$param){
		if(strpos($url,'?')===false){
			$url .= '?';
		}else{
			$url .= '&';
		}
		foreach($param as $k=>$v){
			$url .= "$k=$v&";
		}
		$url = substr($url,0,-1);
		return $url;
	}

	public static function log_2_file($log,$file){
		error_log($log,3,$file);
	}

	public static function exec_sql($dbo,$sql,array $param=array()){
		if(empty($sql)) return true;

		$is_insert = strtolower(substr(trim($sql),0,6))=='insert';
		$is_select = strtolower(substr(trim($sql),0,6))=='select' || strtolower(substr(trim($sql),0,4))=='show';

		try
		{
			$smt      = $dbo->prepare($sql);
			$exec_ret = $smt->execute($param);
		}
		catch(PDOException $e)
		{
			error_log("ERROR CLASS:" . __CLASS__ . ", FUNCTION: " . __FUNCTION__ . ", LINE: " . __LINE__);
			error_log("ERROR - SQL FAILS: $sql");
			error_log("Parameters: " . print_r($param, TRUE));
			error_log(print_r($smt->errorInfo(), TRUE));
			error_log("Exception Message: ".$e->getMessage());
			throw $e; 
		}

		if($is_insert){
			$no_insert_id = array('delayed','ignore','update');
			foreach($no_insert_id as $key){
				if(stripos($sql,$key)){
					return true;
				}
			}
			return $dbo->lastInsertId();
		}else if($is_select){
			return $smt->fetchAll(PDO::FETCH_ASSOC);
		}else{
			return true;
			//return $smt->rowCount();  // no update, return 0, the 0 is false
		}
	}

	/**
	 * get info name
	 *
	 * @param string $type : info type
	 * @param int $id      : info id
	 *
	 * @return $name : info name
	 */
	public static function get_infos_name($type, $id)
	{
		$class_name = AC::$infoType[$type];
		$object = new $class_name();
		$object_detail = $object->get($id);

		$object_name = '';
		foreach (AC::$infoName[$type]['name_field'] as $field)
		{
			if(isset($object_detail->$field)){
				$object_name .= $object_detail->$field." ";
			}
		}
		return $object_name;
	}

	/**
	 * check if concurrent?
	 *
	 * @param string $object : object name
	 * $param int $object_id : object id
	 */
	public static function is_concurrent($object, $object_id, $modify_at)
	{
		$object = new $object();
		$object_detail = $object->get($object_id);
		if ($object_detail->modified_at == $modify_at)
		{
			return false;
		}
		else
		{
			return true;
		}
	}


	/**
	 * get table fields for infos init null data
	 */
	public static function get_table_fields($table,$dbo=null){
		static $table_fields = array();
		if(empty($table_fields[$table])){
			if(is_null($dbo)){
				$rs = Model::selectBySql("show full fields from `$table`");
			}else{
				$rs = CommonUtils::exec_sql($dbo,"show full fields from `$table`");
			}
			$fields = array();
			foreach($rs as $row){
				$fields[] = $row['Field'];
			}
			$table_fields[$table] = $fields;
		}

		return $table_fields[$table];
	}

	/**
	 * get table keys
	 */
	public static function get_table_keys($table){
		static $table_keys = array();
		if(empty($table_keys[$table])){
			$rs = Model::selectBySql("SHOW INDEX FROM `$table`");
			$fields = array();
			foreach($rs as $row){
				if($row['Key_name']=='PRIMARY'){
					$fields[] = $row['Column_name'];
				}
			}
			$table_keys[$table] = $fields;
		}

		return $table_keys[$table];
	}

	/**
	 * json info data
	 */
	public static function json_info_data($action, $field)
	{
		$json_array = array();

		# modify by vanni, for bug:7397
		$len = count($action->cast_id);
		if(!empty($action->cast_id[$field])){
			foreach($action->cast_id[$field] as $i=>$null){
				$json_array[$field][] = array(
					"cast_id"    => 0,
					"name_type"  => $action->name_type[$field][$i],
					"last_name"  => trim($action->name_last[$field][$i]),
					"first_name" => trim($action->name_first[$field][$i]), 
					"alphabet"   => $action->alphabet[$field][$i]
				);
			}
		}
		return json_encode($json_array);

		/* modify by vanni,for bug:7397
		$len = count($action->role_id);
		for ($i=0; $i<$len; $i++)
		{
			$role_id = $action->role_id[$i];
			if ($role_id != $field) continue;
		
			$json_array[$field][] = array("cast_id"=>0,"name_type"=>$action->name_type[$i],"last_name"=>trim($action->name_last[$i]),"first_name"=>trim($action->name_first[$i]), "alphabet"=>$action->alphabet[$i]);
		}

		return json_encode($json_array);
		 */
	}

	/**
	 * format date display
	 */
	public static function formatDate($datetime)
	{
		if($datetime != '0000-00-00 00:00:00')
		{
			$year = substr($datetime, 0, 10);
			$time = substr($datetime, 11, 5);
		}
		else
		{
			$year = '';
			$time = '';
		}

		return array($year, $time);

	}

	/**
	 * check year/month/day
	 *
	 * @param int $year :
	 * @param int $month:
	 * @param int $day  :
	 *
	 * @used by : biography
	 */
	public static function check_date($year, $month, $day)
	{
		if (is_null($year) && is_null($month) && is_null($day))
		{
			return true;
		}
		elseif(is_null($year) || is_null($month) || is_null($day))
		{
			return false;
		}
		if ($year < 0 || $month < 0 || $day < 0)
		{
			return false;
		}
		$isLeap = false;
		if ( $year < 1582 )	$isLeap = ($year % 4 == 0) ? true : false;
		if ( $year % 4 != 0 ) $isLeap = false;
		if ( $year % 100 != 0 ) $isLeap = true;
		if ( $year % 400 != 0 ) $isLeap = true;
		if ( $year % 3200 != 0 ) $isLeap = false;

		if (false == $isLeap && $month == 2 && $day > 28)
		{
			return false;
		}
		if (true == $isLeap && $month == 2 && $day > 29)
		{
			return false;
		}
		if ($month > 12) return false;
		if ($month == 1 || $month == 3 || $month == 5 || $month == 7 || $month == 8 || $month == 10 || $month == 12)
		{
			if ($day > 31) return false;
		}
		if ($month == 4 || $month == 6 || $month == 9 || $month == 11)
		{
			if ($day > 30) return false;
		}

		return true;
	}

	/**
	 * sec transfer to hour:minute:second
	 *
	 * @param int $ss : timestamp
	 *
	 * @used by : action/ChapterGetAction.class.php
	 */
	public static function sec_to_num($ss)
	{
		$hh = (int) floor($ss / 3600);
		$ss -= $hh * 3600;
		$mm = (int) floor($ss / 60);
		$ss -= $mm * 60;

		if ($hh == 0 && $mm == 0 && $ss == 0)
		{
			$hh = $mm = $ss = '00';
		}
		else
		{
			$hh = ($hh < 10 ) ? "0".$hh : $hh;
			$mm = ($mm < 10 ) ? "0".$mm : $mm;
			$ss = ($ss < 10 ) ? "0".$ss : $ss;
		}

		return array($hh, $mm, $ss);
	}

	/**
	 * save publish and unpublish log
	 *
	 * @param string $object : object name
	 * @param string $object_id : object id
	 * @param string $logType : publish or unpublish
	 * @param string $oject_data : js_encode data
	 *
	 * @return int $log_id : audit log id
	 */
	public static function save_log($object, $object_id, $logType, $object_data)
	{

		$log = new audit_log();
		$log->item_type_id = item_type::getItemIDByName($object);
		$log->item_id = $object_id;
		$log->modified_at = date("Y-m-d H:i:s");
		$log->modified_by = CommonUtils::get_user();
		$log->status = ($logType == AC::LOG_OP_DELETE) ? AC::STATUS_DELETED : AC::STATUS_NEW;
		$log->remarks= AC::$log_type[$logType]." {$object} success";
		$log->action = $logType;
		$log->data = $object_data;
		return Model::$dbo['w']->save($log);

	}

	public static function getDiffFolderItem($folder, $act, &$old_data, $unpublish=0, $is_published=0){
		$folder_items  = &$old_data['folder_item'];

		$item_list = array();

		$folder_items = is_null($folder_items) ? array() : $folder_items;
		$sort = array();
		foreach ($folder_items as $item)
		{
			if($item['folder_id'] != $folder['id']) continue;
			#if($item[ArrayDiff::STATUS_KEY] == ArrayDiff::STATUS_DELETE) continue;				

			$row['id']    = $item['item_id'];
			$the_folder   = $old_data['folder'][$item['folder_id']];
			$item_type_id = $the_folder['folder_item_type_id'];
			$item_table   = ($item_type_id == AC::FOLDER_TYPE_VIDEO) ? 'video' : 'image';
			$item_publish = publish_log::getPublishLog($item_table, $item['item_id']);
			//if ($item_publish->status == AC::STATUS_UNPUBLISH) continue;
			
			if(empty($old_data[$item_table.'-language']) || empty($old_data[$item_table])) continue;
			if(empty($old_data[$item_table][$item['item_id']])) continue;

			$item_obj     = $old_data[$item_table][$item['item_id']];
			
			$en_unique_key = $item['folder_id'].$item['item_id'].language::getLanguageID(AC::LANGUAGE_EN);
			$zh_unique_key = $item['folder_id'].$item['item_id'].language::getLanguageID(AC::LANGUAGE_ZH);
			if(empty($old_data['folder_item-language'][$en_unique_key])){
				$the_object_en = array('title'=>'', ArrayDiff::STATUS_KEY=> ArrayDiff::STATUS_NONE);
			}else{
				$the_object_en = $old_data['folder_item-language'][$en_unique_key];
			}
			if(empty($old_data['folder_item-language'][$zh_unique_key])){
				$the_object_zh = array('title'=>'', ArrayDiff::STATUS_KEY=> ArrayDiff::STATUS_NONE);
			}else{
				$the_object_zh = $old_data['folder_item-language'][$zh_unique_key];
			}

			$row['title'] = 'ID:' . $item['item_id'] . '<br />' 
							. htmlentities($the_object_zh['title'], ENT_QUOTES, 'UTF-8') . ' ' 
							. htmlentities($the_object_en['title'], ENT_QUOTES, 'UTF-8');
			$row['src'] = $old_data[$item_table][$item['item_id']]['source_url'];
			$row['flag'] = episode_video::getEpisodeID($item['item_id']);

			if($item_table == 'video' && $old_data[$item_table][$item['item_id']]['vi_status']!=AC::VIDEO_STATUS_UPLOADED){
				switch($old_data[$item_table][$item['item_id']]['vi_status']){
					case AC::VIDEO_STATUS_QUEUE :
						$row['thumb'] = AC::PDES_FLASH_ASSETS_PROCESS;
						break;
					case AC::VIDEO_STATUS_WAITING :
						$row['thumb'] = AC::PDES_FLASH_ASSETS_WAIT;
						break;
					case AC::VIDEO_STATUS_FAILED  :
						$row['thumb'] =  AC::PDES_FLASH_ASSETS_FAILURE; 
						break;
				}
			}else{
				$row['thumb'] = $old_data[$item_table][$item['item_id']]['thumbnail_url'];
			}

			if($act == 'view'){
				if($unpublish){
					#if($item[ArrayDiff::STATUS_KEY] == ArrayDiff::STATUS_DELETE) continue;				
					$row['status'] = '';
				}else{
					if($is_published){
						if($item[ArrayDiff::STATUS_KEY] == ArrayDiff::STATUS_DELETE) continue;				
						
						if($the_object_zh[ArrayDiff::STATUS_KEY]==ArrayDiff::STATUS_NONE && $the_object_en[ArrayDiff::STATUS_KEY]==ArrayDiff::STATUS_NONE){
							#$row['status'] = AC::$folder_status[$item[ArrayDiff::STATUS_KEY]];
							$row['status'] = AC::$folder_status[$item_obj[ArrayDiff::STATUS_KEY]];
						}else{
							#$row['status'] = AC::$folder_status[$the_object[ArrayDiff::STATUS_KEY]];
							$row['status'] = AC::$folder_status[ArrayDiff::STATUS_UPDATE];
						}
					}else{
						$row['status'] = '';
					}
				}
			}else{
				#if($item[ArrayDiff::STATUS_KEY] == ArrayDiff::STATUS_DELETE) continue;				
				$row['status'] = '';
			}
			$sort[] = $item['rank'];
			$item_list[] = $row;

		}
		array_multisort($sort, SORT_ASC, $item_list);
		return array(
			'fid'   => $folder['id'],
			'total' => count($item_list),
			'ftype' => $folder['folder_item_type_id'],
			'fspec' => $folder['folder_type_id'],
			'fname' => htmlentities($folder['system_label'], ENT_QUOTES, 'UTF-8'),
			'items' => $item_list
		);
	}
	public static function is_published($table,$id,$status=AC::STATUS_PUBLISH){
		$sql = '
			select l.status from publish_log l inner join item_type i on l.item_type_id=i.id and i.system_label=:tab
			where l.item_id=:id order by l.id desc limit 1
			';
		$rs = Model::selectBySql($sql,array(':tab'=>$table,':id'=>$id));
		if($rs){
			return $rs[0]['status'] == $status;
		}else{
			return false;
		}
	}

	/**
	 * 查詢最後的Publish狀態是否等於傳入的狀態,成功返回true,否則返回 false
	 * 例如：
	 *   1: 查詢 status = publish 
	 *      如果有publish過，並且publish之後未再unpublish，那麼返回 true
	 *   2: 查詢 status = unpublish
	 *      如果有unpublish過，並且unpublish之後未再publish，那麼返回 true
	 *
	 * @param string $table table name
	 * @param int $id query id
	 * @param int $status publish status see defined in AC class
	 * @return bool
	 */
	public static function checkLastPublishStatus($table,$id,$status=AC::STATUS_PUBLISH){
		if(AC::STATUS_PUBLISH == $status)
		{
			$publish   = AC::STATUS_PUBLISH;
			$unpublish = AC::STATUS_UNPUBLISH;
		}
		elseif(AC::STATUS_PUBLISH_PREMIUM == $status)
		{
			$publish   = AC::STATUS_PUBLISH_PREMIUM;
			$unpublish = AC::STATUS_UNPUBLISH_PREMIUM;
		}
		elseif(AC::STATUS_UNPUBLISH == $status)
		{
			$unpublish = AC::STATUS_PUBLISH;
			$publish   = AC::STATUS_UNPUBLISH;
		}
		elseif(AC::STATUS_UNPUBLISH_PREMIUM == $status)
		{
			$unpublish = AC::STATUS_PUBLISH_PREMIUM;
			$publish   = AC::STATUS_UNPUBLISH_PREMIUM;
		}

		# sql = select * from log where publish=yes and id > ifnull( (select max(id) from log where unpublish=yes) ,0)

		$maxid = 'ifnull(';
		$maxid.= '(select max(l.id) from publish_log l inner join item_type i on l.item_type_id=i.id and i.system_label=:tab ';
		$maxid.= 'where l.item_id=:id and l.status=:unpublish)';
		$maxid.= ',0)';

		$query = 'select a.status from publish_log a inner join item_type b on a.item_type_id=b.id and b.system_label=:tab ';
		$query.= "where a.item_id=:id and a.status=:publish and a.id>$maxid order by a.id desc limit 1";

		$rs = Model::selectBySql($query, array(':tab'=>$table,':id'=>$id,':publish'=>$publish,':unpublish'=>$unpublish));
		return isset($rs[0]['status']);
	}

	public static function GetVideoInformation($file) {
        if (!file_exists($file)) {
            return FALSE;
        }
        $command = "/usr/bin/mediainfo -f --Language=raw \"{$file}\"";
        exec($command, $command_output, $ret);

        $information = array();
        $current_section = '';
        foreach ($command_output as $line) {
            $line = trim($line);
            if ($line == "") {
                continue;
            }

            $tmp = explode(" : ", $line);
            if (count($tmp) == 1) {
                $current_section = $tmp[0];
            } else {
                $information[$current_section][trim($tmp[0])] = trim($tmp[1]);
            }            
        }

        return $information;
    }
 
	public static function getAdminMail($type='default'){
		$config = ConfigReaderFactory::getInstance()->getConfigReader(AC::CONFIG_FILE)->getConfig();
		$mailto = $config->xpath("/config/adminMailList/$type");
		if(isset($mailto[0])){
			return (string)$mailto[0];
		}else{
			return '';
		}
	}

	public static function getFolderTypeList(){
		$data = array();
		$result = Model::selectBySql('SELECT * FROM folder_type');
		foreach($result as $row){
			if($row['folder_item_type_id']==AC::FOLDER_TYPE_IMAGE){
				$data['image'][$row['id']]=$row['system_label'];
			}elseif($row['folder_item_type_id'] == AC::FOLDER_TYPE_VIDEO){
				$data['video'][$row['id']]=$row['system_label'];
			}
		}
		return $data;
	}

	/** 
	 * CPL : Company Code & Programme No. 
	 * get programme ids by programme company code & programme No.
	 */
	public static function getProgrammeIdsByCPL($cplWhereArray,$field,$operation,$dbo=false){
		$index = array_search('cpl_company_code',$field);
		if($operation[$index]=='ne'){
			$having = ' having cnt=total or total=0';
		}else{
			$having = '';
		}
		$cplWhere = '('. implode(') OR (', $cplWhereArray). ')';
		$cplWhere = str_replace('`findApi`.company_code_cpl','concat(ifnull(cpl_company_code,""), " ", ifnull(cpl_id,""))',$cplWhere);

		$sql = '
			select id, count(0) cnt,
			  (select count(0) from programme_cpl inSql where inSql.programme_id=p.id) total
			from programme p
			left join programme_cpl cp on p.id=cp.programme_id
			where '.$cplWhere.' group by id'.$having;

		if($dbo){
			$programmeIDs =	CommonUtils::exec_sql($dbo->getDbHandle(),$sql);
		}else{
			$programmeIDs =	Model::selectBySql($sql);
		}

		$ids = array();
		foreach($programmeIDs as $row){
			$ids[] = $row['id'];
		}
		return $ids;
	}

	public static function getProgrammeIdsByTitle($titleWhereArray,$field,$operation,$dbo=false){
		$titleWhere = '('. implode(') AND (', $titleWhereArray). ')';
		$title_index = array_search('title',$field);
		if($operation[$title_index]=='ne'){
			$having = 'having cnt=total_cnt';
		}else{
			$having = '';
		}
		$sql = '
			select programme_id as id,count(programme_id) as cnt,
			(select count(0) from `programme-language` intab where intab.programme_id=findApi.programme_id) as total_cnt
			from `programme-language` as findApi
			where ' . $titleWhere . '
			group by programme_id ' . $having ;

		if($dbo){
			$programmeIDs =	CommonUtils::exec_sql($dbo->getDbHandle(),$sql);
		}else{
			$programmeIDs =	Model::selectBySql($sql);
		}

		$ids = array();
		foreach($programmeIDs as $row){
			$ids[] = $row['id'];
		}
		return $ids;
	}

	public static function getProgrammeIdsByPath($pathWhereArray){
		$pathWhere = '('. implode(') AND (', $pathWhereArray). ')';
		$sql = 'SELECT id FROM programme AS findApi WHERE '. $pathWhere ;
		$programmeIDs =	Model::selectBySql($sql);

		$ids = array();
		foreach($programmeIDs as $row){
			$ids[] = $row['id'];
		}
		return $ids;
	}

	public static function P_getMediaIdsByTitle($type,$table,$titleWhereArray,$field,$operation){
		$titleWhere = '('. implode(') AND (', $titleWhereArray). ')';
		$titleWhere = str_replace($type.'_title','title',$titleWhere);
		$title_index = array_search($type.'_title',$field);
		if($operation[$title_index]=='ne'){
			$having = 'having cnt=total_cnt';
		}else{
			$having = '';
		}
		$sql = "
			select {$type}_id as id,count({$type}_id) as cnt,
			(select count(0) from `{$table}-language` intab where intab.{$type}_id=findApi.{$type}_id) as total_cnt
			from `{$table}-language` as findApi
			where $titleWhere
			group by {$type}_id $having";

		$mideaIDs =	Model::selectBySql($sql);

		$ids = array();
		foreach($mideaIDs as $row){
			$ids[] = $row['id'];
		}
		return $ids;
	}

	public static function getMediaIdsByTitle($type,$titleWhereArray,$field,$operation){
		$titleWhere = '('. implode(') AND (', $titleWhereArray). ')';
		$titleWhere = str_replace($type.'_title','title',$titleWhere);
		$title_index = array_search($type.'_title',$field);
		if($operation[$title_index]=='ne'){
			$having = 'having cnt=total_cnt';
		}else{
			$having = '';
		}
		$sql = "
			select {$type}_id as id,count({$type}_id) as cnt,
			(select count(0) from `{$type}-language` intab where intab.{$type}_id=findApi.{$type}_id) as total_cnt
			from `{$type}-language` as findApi
			where $titleWhere
			group by {$type}_id $having";

		$mideaIDs =	Model::selectBySql($sql);

		$ids = array();
		foreach($mideaIDs as $row){
			$ids[] = $row['id'];
		}
		return $ids;
	}

	/**
	 *  $name_type : name\cast name\other name\cast nickname  
	 *  
	 *  Name          = real_first_name + real_last_name
	 *  Cast Name     = first_name + last_name
	 *  Other Name    = other_name
	 *  Cast Nickname = nickname
	 */
	public static function getCastIdsByName($name_type,$nameWhere,$field,$operation,$zh,$en){
		$name_index = array_search($name_type,$field);
		if($operation[$name_index]=='ne'){
			$not = ' and cnt=total_cnt';
		}else{
			$not = ' ';
		}
		$sql = '
			select 
				count(cast_id) as cnt,
				(select count(cast_id) from `cast-language` intab where intab.cast_id=findApi.cast_id) as total_cnt,
				cast_id,
				other_name,
				nickname,
				case language_id
					when '.$zh.' then concat(real_last_name,real_first_name)
					when '.$en.' then concat(real_first_name," ",real_last_name) 
				end as real_name,
				case language_id
					when '.$zh.' then concat(last_name,first_name)
					when '.$en.' then concat(first_name," ",last_name) 
				end as cast_name 
			from `cast-language` as findApi 
			group by cast_id,other_name,nickname,real_name,cast_name having ' . $nameWhere . $not;

		#echo $sql;
		$castIDs =	Model::selectBySql($sql);

		$ids = array();
		foreach($castIDs as $row){
			$ids[] = $row['cast_id'];
		}
		return $ids;
	}
	
	/*
	 *get mis data by MIS API
	 */
	public static function getMisData( $api, $params )
	{
		require_once( 'TVB/pms/pdes/common/util/MisApi.class.php' );
		require_once( 'TVB/pms/pdes/common/util/MisApiConfig.php' );
		
		$webService = new MisApi( '/data/pms/pdes/conf/MisApiConfig.xml' );
		$file = $webService->getDataByApi( $api, 'tvb', $params );
		
		if( file_exists($file) ){
			$data = simplexml_load_file( $file );
			$data = Model::object2array( $data );
		}else{
			$data = array();
		}
		
		return $data;
	}

    public static function filterC2A0($table_name, $primary_key = array(), $param = array())
    {
        if (empty($table_name) || empty($primary_key) || empty($param)){
            return false;
        }

        foreach ($param as $field) {
            $aParam[] = $field . " = REPLACE(" . $field . ", UNHEX('C2A0'), ' ')";
        }
        $kParam = array();
        foreach ($primary_key as $key=>$value) {
            $kParam[':' . $key] = $value;
        }

        $sql = "
            UPDATE `" . $table_name . "` SET " .
                implode(',', $aParam) . "
            WHERE `" . key($primary_key) . "` = :" . key($primary_key);
        $rid = Model::updateBySql($sql, $kParam);
        return $rid;
    }

    public static function checkMissingSDESProgrammeNoInPDES($start_broadcast_datetime, $end_broadcast_datetime)
    {
        $sdes_data = PMSWebServiceDataSyncHelper::getProgrammeListByBroadcastDatetime($start_broadcast_datetime, $end_broadcast_datetime);

        $programme_no = array();
        foreach ($sdes_data as $row) {
            $programme_no[] = $row['program_no'];
        }

        if (empty($programme_no)) {
            return array();
        } else {
            $cpl_id = "'" . implode("','", $programme_no) . "'";
        }

        $sql = "SELECT p.`cpl_id` FROM programme_cpl p
            WHERE p.`cpl_company_code`='TVB' AND p.`cpl_id` IN ({$cpl_id})";
        $pdes_data = Model::selectBySql($sql);

        $pdes_programme_no = array();
        foreach ($pdes_data as $row) {
            $pdes_programme_no[] = $row['cpl_id'];
        }

        if (empty($pdes_programme_no)) {
            return $sdes_data;
        }

        foreach ($sdes_data as $key=>$row) {
            if (in_array($row['program_no'], $pdes_programme_no)) {
                unset($sdes_data[$key]);
            }
        }

        return $sdes_data;
    }

    public static function getVideoInformationByViExportId($vi_export_id ,$vi_source_id)
    {
        if(empty($vi_export_id) || empty($vi_source_id))
        {
            return FALSE;
        }
        $sql = 'SELECT v.id, v.programme_id, v.vi_id FROM video v left join video_export ve on ve.video_id = v.id
            where ve.export_id = :export_id  and v.vi_id = :source_id';
        $sql_array = array(':export_id'=>$vi_export_id,':source_id'=>$vi_source_id);
        $videos = Model::selectBySql($sql,$sql_array);
        $video_info = array();
        if(!empty($videos))
        {
            foreach($videos as $video)
            {
                $video_array = array();
                $folder_ids = array();
                if(empty($video))
                {
                    continue;
                }
                $programme_id =  $video['programme_id'];
                $video_id = $video['id'];
                $sql_pro = 'SELECT *  FROM `programme` p where id = :pid';
                $programme = Model::selectBySql($sql_pro,array(':pid'=>$programme_id));
                $pro_path = empty($programme) ? '' : $programme[0]['path'];
                $onair_episode_no = self::getOnairEpisodeByProgrammeId($programme_id);
                $sql_pro_lang = 'SELECT *  FROM `programme-language` p where programme_id = :pid';
                $pro_language = Model::selectBySql($sql_pro_lang,array(':pid'=>$programme_id));
                $pro_title_cn = $pro_language[0]['title'];
                $pro_title_en = $pro_language[1]['title'];

                $sql_folder = '
                    SELECT f.id FROM
                        folder f
                    left join folder_item fi on fi.folder_id = f.id
                    where item_id = :vid and f.folder_item_type_id = 1
                    ';
                $folder_data = Model::selectBySql($sql_folder,array(':vid'=>$video_id));
                if($folder_data)
                {
                    foreach($folder_data as $val)
                    {
                        $folder_ids[] = $val['id'];
                    }
                }
                $folder = self::getFolderDetailByFolderIds($folder_ids,$video_id);

                $video_array = array(
                    'video_id'=>$video_id,
                    'programme_id'=>$programme_id,
                    'programme_path'=>$pro_path,
                    'on_aire_episode_no'=>$onair_episode_no,
                    'programme_chi_title'=>$pro_title_cn,
                    'programme_eng_title'=>$pro_title_en,
                    'folders'=>$folder
                );
                $video_info[] = $video_array;
            }
        }
        return empty($videos) ? FALSE : $video_info;
    
    }

    public static function getImageInformationByIiExportId($ii_export_id ,$ii_source_id)
    {
        if(empty($ii_export_id) || empty($ii_source_id))
        {
            return FALSE;
        }
        $sql = 'SELECT i.id, i.programme_id, i.ii_id  FROM pdes.image i
            left join image.export ie on ie.source_id = i.ii_id
            where ie.id = :export_id and i.ii_id = :source_id';
        $sql_array = array(':export_id'=>$ii_export_id,':source_id'=>$ii_source_id);
        $images = Model::selectBySql($sql,$sql_array);
        $image_info = array();
        if(!empty($images))
        {
            foreach($images as $image)
            {
                $image_array = array();
                $folder_ids = array();
                if(empty($image))
                {
                    continue;
                }
                $programme_id =  $image['programme_id'];
                $image_id = $image['id'];
                $sql_pro = 'SELECT *  FROM `programme` p where id = :pid';
                $programme = Model::selectBySql($sql_pro,array(':pid'=>$programme_id));
                $pro_path = empty($programme) ? '' : $programme[0]['path'];
                $onair_episode_no = self::getOnairEpisodeByProgrammeId($programme_id);
                $sql_pro_lang = 'SELECT *  FROM `programme-language` p where programme_id = :pid';
                $pro_language = Model::selectBySql($sql_pro_lang,array(':pid'=>$programme_id));
                $pro_title_cn = $pro_language[0]['title'];
                $pro_title_en = $pro_language[1]['title'];

            
                $sql_folder = 'SELECT f.id FROM
                                folder f
                                left join folder_item fi on fi.folder_id = f.id
                                where fi.item_id = :image_id  and f.folder_item_type_id = 2
                                ';
                $folder_data = Model::selectBySql($sql_folder,array(':image_id'=>$image_id));
                if($folder_data)
                {
                    foreach($folder_data as $val)
                    {
                        $folder_ids[] = $val['id'];
                    }
                }
                $folder = self::getFolderDetailByFolderIds($folder_ids,$image_id);
                 
                $image_array = array(
                    'image_id'=>$image_id,
                    'programme_id'=>$programme_id,
                    'programme_path'=>$pro_path,
                    'on_aire_episode_no'=>$onair_episode_no,
                    'programme_chi_title'=>$pro_title_cn,
                    'programme_eng_title'=>$pro_title_en,
                    'folders'=>$folder
                );
                $image_info[] = $image_array;
            }
        }
        return empty($images) ? FALSE : $image_info;

    } 



    public static function getFolderDetailByFolderIds($fids,$itemid)
    {
        $folders = array();
        if(empty($fids) || empty($itemid))
        {
            return $folders;
        }
        if(!empty($fids))
        {
            foreach($fids  as  $fid)
            {
                $sql_folder_title = 'SELECT title FROM `folder-language` f where folder_id = :fid';
                $folder_title_data = Model::selectBySql($sql_folder_title,array(':fid'=>$fid));
                $folder_title_cn = empty($folder_title_data[0]['title']) ? '' : $folder_title_data[0]['title'] ; 
                $folder_title_en = empty($folder_title_data[1]['title']) ? '' : $folder_title_data[1]['title'] ; 
                
                $sql_folder = 'SELECT system_label as folder_type FROM folder_type f where id = 
                                    (select folder_type_id from folder where id = :fid)';
                $folder_type_data = Model::selectBySql($sql_folder,array(':fid'=>$fid));
                $folder_type = $folder_type_data[0]['folder_type'];

                $sql_folder_item = 'SELECT title FROM `folder_item-language` f where folder_id = :fid and item_id = :itemid';
                $folder_item_data = Model::selectBySql($sql_folder_item,array(':fid'=>$fid,':itemid'=>$itemid));
                $folder_item_cn = empty($folder_item_data[0]['title']) ? '' : $folder_item_data[0]['title'] ;
                $folder_item_en = empty($folder_item_data[1]['title']) ? '' : $folder_item_data[1]['title'] ; 
                $folders[$fid] = array(
                    'folder_title_chi'=>$folder_title_cn,
                    'folder_title_eng'=>$folder_title_en,
                    'folder_type'=>$folder_type,
                    'item_title_chi'=>$folder_item_cn,
                    'item_title_eng'=>$folder_item_en
                );
            }
        }
        return $folders;
    
    }

    public static function getOnairEpisodeByProgrammeId($pid)
    {
        if(empty($pid))
        {
            return FALSE;
        }
        $sql = 'SELECT onair_episode_no FROM episode e where programme_id = :pid';
        $data = Model::selectBySql($sql,array(':pid'=>$pid));
        if($data)
        {
            foreach($data as $val)
            {
                $ret[] = $val['onair_episode_no'];
            }
        }
        return empty($data) ? FALSE : implode(",", $ret);
    }


    public static function decode_field($data,$field)
    {
        $old_fields = array();
        if(!empty($data) && isset($data->$field))
        {
            $field_array = json_decode($data->$field);
            if(isset($field_array->$field))
            {
                foreach($field_array->$field as $val)
                {
                    $old_fields[] = isset($val->first_name) ? $val->first_name : '';
                }
            }
        }
        $old_fields = implode("\n",$old_fields);
        return empty($old_fields) ? '' : $old_fields;
    }

	/*
    public static function  format_field($obj,$field)
    {

        $infos = array();
        $info = array();
        if(!empty($obj->$field))
        {
            if(preg_match('/^\|?\s*(\d{2})\s*\|(.*)/',trim($obj->$field)))
            {
                $ret = array_filter(preg_split('/(\d{2})/',$obj->$field,-1));
                foreach($ret as $value)
                {
                    $arr = array_filter(explode('|',trim($value)));
                    if(isset($arr[1]))
                    {
                        $tmp = isset($arr[2]) ?  trim($arr[2]) : '';
                        $first_name  = !empty($tmp) ? trim($arr[1]).'('.trim($arr[2]).')' : trim($arr[1]) ;
                        if(!empty($first_name))
                        {
                            $info[] = array("cast_id"=>0,"name_type"=>11,"last_name"=>'',"first_name"=>$first_name, "alphabet"=>1);
                        }
                    }
                }
                $infos[$field] = $info;
            }
            else
            {
                $matches = explode(',',trim($obj->$field));
                foreach($matches as $value)
                {
                    $val = trim($value);
                    if(!empty($val))
                    {
                        $info[] = array("cast_id"=>0,"name_type"=>11,"last_name"=>'',"first_name"=>$val, "alphabet"=>1);
                    }
                }
                $infos[$field] = $info;
            }
        }
        return json_encode($infos);
    }
	*/

    public static function  format_field($obj,$field)
    {
        $result = array();
        if(!empty($obj->$field))
        {
            $infos = array();
            $tmp = explode("\n",$obj->$field);
            foreach($tmp as $tmp1) {
                $tmp2 = explode(",", $tmp1); 
                foreach($tmp2 as $name) {
                    $name = trim($name); 
                    if ($name) { 
                        $other_name = self::getname($name);
                        if(is_array($other_name))
                        {
                            foreach($other_name as $val)
                            {
                                $infos[] = array("cast_id"=>0,"name_type"=>11,"last_name"=>'',"first_name"=>$val, "alphabet"=>1);
                            }
                        }
                        else
                        {
                            $infos[] = array("cast_id"=>0,"name_type"=>11,"last_name"=>'',"first_name"=>self::getname($name), "alphabet"=>1);
                        }
                    }
                }
            }        
            $result[$field] = $infos;
        }
        return json_encode($result);
    }

    private function getname($str)
    {
        if(preg_match('/^\|?\s*(\d{2})\s*\|(.*)/',$str))
        {
            $result = array();
            $ret = array_filter(preg_split('/(\d{2})/',$str,-1));
            foreach($ret as $value)
            {
                $arr = array_filter(explode('|',trim($value)));
                if(isset($arr[1]))
                {
                    $tmp = isset($arr[2]) ?  trim($arr[2]) : '';
                    $first_name  = !empty($tmp) ? trim($arr[1]).'('.trim($arr[2]).')' : trim($arr[1]) ;
                    if(!empty($first_name))
                    {
                        $result[] = $first_name;
                    }
                }
            }
            return empty($result) ? '' : $result;
        }
        return $str;
    }

    public function showPublishButton($flag_premium, $permission)
    {
        $flag_permission = (isset($permission['all']) && $permission['all'] == TRUE) || (isset($permission['proofread']) && $permission['proofread'] == TRUE);
        if ($flag_permission == TRUE) {
            FormHelper::SubmitButton('proof', 'Proof-read');
			#comment by vanni
            #if($flag_premium == TRUE) {
            #    FormHelper::SubmitButton('proof_premium', 'Proof-read (Premium)');
            #}
        }
    }
    
    public function showUnpublishButton($data, $permission)
    {
        $flag_permission = (isset($permission['all']) && $permission['all'] == TRUE) || (isset($permission['proofread']) && $permission['proofread'] == TRUE);
        if ($flag_permission == TRUE) {             
			if(
				!isset($data['special_operation_premium']) 
				&& isset($data['publishLog']->non_premium->status)  
			    && AC::STATUS_PUBLISH == $data['publishLog']->non_premium->status
			)
			{
                FormHelper::SubmitButton('unpublish', 'Unpublish');
			}
			else if(
				isset($data['special_operation_premium']) 
				&& $data['special_operation_premium'] == TRUE 
				&& isset($data['publishLog']->premium) 
			    && AC::STATUS_PUBLISH_PREMIUM == $data['publishLog']->premium->status
			)
			{
                FormHelper::SubmitButton('unpublish_premium', 'Unpublish (Premium)');
            }
        }
    }
    
    public function showDeleteButton($publish_log)
    {
		$status = AC::STATUS_UNPUBLISH_PREMIUM;
		$non_status = AC::STATUS_UNPUBLISH;

		$premium_ok     = isset($publish_log->premium)     ? ($publish_log->premium->status==$status) : true;
		$non_premium_ok = isset($publish_log->non_premium) ? ($publish_log->non_premium->status==$non_status) : true;

		if( $premium_ok && $non_premium_ok )
		{
            FormHelper::SubmitButton('delete', 'Delete');
        }
    }

	public function isPremiumProgramme($type,$id){
		if('programme' == $type){
			$sql = 'select premium_flag from programme where id=:id and premium_flag=1';
		}elseif('episode' == $type){
			$sql = 'select p.premium_flag from episode e inner join programme p on e.programme_id=p.id and p.premium_flag=1 where e.id=:id';
		}
		$rs = Model::selectBySql($sql,array(':id'=>$id));
		return isset($rs[0]['premium_flag']);
	}

    public static function checkVideoStatus($folders)
    {
        if (empty($folders))    $folders    =   '""'; 

		/** Check CatchUP Folder Only.Add by vanni at 2011-05-10 for bug 6587 */
        $sql=   '
            SELECT
                fi.item_id      AS  itemID
            FROM
                folder      AS  f,
                folder_item AS  fi,
                video       AS  v
            WHERE
                f.id = fi.folder_id
                AND v.id = fi.item_id
                AND v.vi_status <> "'. AC::VIDEO_STATUS_UPLOADED. '"
                AND v.status <>"'. AC::STATUS_DELETED. '"
                AND f.folder_item_type_id = "'.AC::FOLDER_TYPE_VIDEO. '"
				AND f.folder_type_id = "'.AC::VIDEO_CATCHUP.'"
                AND f.id IN ('. $folders .')
            Limit 1
            ';
        $result = Model::selectBySql($sql);
        return  empty($result[0]['itemID']) ?   NULL    :   $result;
    }

	/*
	 * by donald
	 * at 2011-10-24
	 */
    public static function isAllVideosReady($folders)
    {
		if (empty($folders)) {
			return TRUE;
		}

        $sql = '
            SELECT fi.item_id AS itemID
            FROM folder AS f, folder_item AS fi, video AS v
            WHERE
                f.id = fi.folder_id
                AND v.id = fi.item_id
                AND v.vi_status <> "'. AC::VIDEO_STATUS_UPLOADED. '"
                AND v.status <>"'. AC::STATUS_DELETED. '"
                AND f.folder_item_type_id = "'.AC::FOLDER_TYPE_VIDEO. '"
                AND f.id IN ('. $folders .')
            Limit 1
            ';
        $result = Model::selectBySql($sql);

        return empty($result[0]['itemID']) ? TRUE : FALSE;
    }



	############################### Proofread new flow is functions ###############################
	/**
	 * Send Data to ViiiProcess
	 */
	public static function sendDataToIiViProcess($dataArray){/*{{{*/
		$programme_id = $dataArray['programme_id'];
		$programme = new programme;
		$programme_detail = $programme->get($programme_id);
		if (!empty($programme_detail->priority)) {
			$str = "/config/consumer[@name='videoImageHandler_Priority']";
		} else {
			$str = "/config/consumer[@name='videoImageHandler']";
		}

		$config = ConfigReaderFactory::getInstance()->getConfigReader(AC::CONFIG_MQ)->getConfig();
		$consumerConfig = $config->xpath($str);

		$broker = (string) $consumerConfig[0]->broker;
		$queue  = (string) $consumerConfig[0]->queue;
		return MessageHelper::sendMessage($broker, $queue, $dataArray);
	}/*}}}*/

	/**
	 * Get Folder Type by ii_id from db2
	 * @return Array($ii_id=>array($folder_type=>$watermark..),..)
	 */
	public static function getFolderTypeByIiId($dbo ,array $ii_ids,$premium=false){/*{{{*/
		if(empty($ii_ids)) return array();
		$premium = $premium ? 'p_' : '';
		$ids = implode(',',array_keys($ii_ids)); // all ii_ids
		$sql = "
			SELECT 
			  i.ii_id,
			  GROUP_CONCAT(DISTINCT CONCAT(ft.path,IFNULL(ifc.watermark_id,0))) AS folder_type
			FROM {$premium}folder_item AS fi 
			  INNER JOIN {$premium}folder AS f
				ON fi.folder_id=f.id AND f.folder_item_type_id=". AC::FOLDER_TYPE_IMAGE . "
			  INNER JOIN folder_type AS ft
				ON f.folder_type_id=ft.id
			  INNER JOIN {$premium}image AS i
				ON fi.item_id=i.id
			  LEFT JOIN `{$premium}image_folder-config` AS ifc ON ifc.folder_id=f.id
			WHERE i.ii_id IN(".$ids.')
			GROUP BY i.ii_id;
		';
		#error_log($sql);
		$rs = CommonUtils::exec_sql($dbo, $sql);
		$has_folder_image = array();
		foreach($rs as $row){
			$folder_types = explode(',',$row['folder_type']);
			foreach($folder_types as $_folder_type){
				$folder_type = substr($_folder_type,0,-1);
				$watermark   = substr($_folder_type,-1);
				if(empty($has_folder_image[$row['ii_id']][$folder_type])){
					$has_folder_image[$row['ii_id']][$folder_type] = $watermark;
				}
			}
		}

		foreach($ii_ids as $id=>$type){
			$ii_ids[$id] = isset($has_folder_image[$id]) ? $has_folder_image[$id] : array();
			$folder_image = isset($has_folder_image[$id]) ? $has_folder_image[$id] : array();
			if($type) // video thumbnail or chapter thumbnail
			{
				$ii_ids[$id]['video_thumbnail'] = 0;
			}
			elseif(array_key_exists('stage_photo',$folder_image)||array_key_exists('synopsis_image',$folder_image))
			{
				$ii_ids[$id]['thumbnail'] = 0;
			}
		}
		return $ii_ids;
	}/*}}}*/

	/**
	 * Get All vi_ids & ii_ids By programme_id from db2
	 * @return array('vi_ids'=>array(..),'ii_ids'=>array(..))
	 */
	public static function getProgrammeMediaIds($dbo,$programme_id,$premium=''){/*{{{*/
		$premium = $premium ? 'p_' : '';
		$sql = "
			select vi_id as id, 'vi_ids' as type, 0 as thumbnail from {$premium}video   where status=".AC::STATUS_NEW." and programme_id=$programme_id and vi_id>0 union 
			select ii_id as id, 'ii_ids' as type, 1 as thumbnail from {$premium}video   where status=".AC::STATUS_NEW." and programme_id=$programme_id and ii_id>0 union
			select ii_id as id, 'ii_ids' as type, 0 as thumbnail from {$premium}image   where status=".AC::STATUS_NEW." and programme_id=$programme_id and ii_id>0 union
			select ii_id as id, 'ii_ids' as type, 1 as thumbnail from {$premium}chapter where status=".AC::STATUS_NEW." and ii_id>0 and video_id in(select id from {$premium}video where programme_id=$programme_id)
		";
		$rs = CommonUtils::exec_sql($dbo, $sql);
		$medias = array('ii_ids'=>array(),'vi_ids'=>array());
		foreach($rs as $row){
			if('ii_ids'==$row['type']){
				$medias[$row['type']][$row['id']] = $row['thumbnail'];
			}else{
				$medias[$row['type']][]=$row['id'];
			}
		}
		return $medias;
	}/*}}}*/

	/**
	 * if cast exists in the json string then return true else return false
	 * @param string $json jsonstring
	 * @param int $cast_id
	 * @return bool
	 */
    public static function existsCastInJson($json,$cast_id){/*{{{*/
        $casts = json_decode($json,1);
		if($casts) foreach($casts as $data){
            if(is_array($data)) foreach($data as $row){
                if($row['cast_id'] == $cast_id){
                    return true;
                }
            }
        }
        return false;
    }/*}}}*/

	/**
	 * get cast ids by casts-json-string
	 * @param string $json jsonstring
	 * @return array
	 */
	public static function getCastIdsByCastJson($json){
        $casts = json_decode($json,1);
		$ids   = array();
		if($casts) foreach($casts as $data){
            if(is_array($data)) foreach($data as $row){
                if($row['cast_id']){
                    $ids[] = $row['cast_id'];
                }
            }
        }
        return $ids;
	}

	/**
	 * Get ii/vi ids from db3 data
	 */
	public function getMediaIdsByDb3Data($dbHandle, array &$db3_data, $premium){
		$media_ids = array('ii_ids'=>array(),'vi_ids'=>array());
		foreach($db3_data['update'] as $row){
			switch($row['type']){
			case'Chapter':
				$media_ids['ii_ids'][$row['data']['image_id']] = 1;
				break;
			case 'Image':
				$media_ids['ii_ids'][$row['data']['ii_id']] = 0;
				break;
			case 'Video':
				$media_ids['ii_ids'][$row['data']['image_id']] = 1;
				$media_ids['vi_ids'][] = $row['data']['vi_id'];
				break;
			case 'Programme':
				if($row['data']['banner_image']) $media_ids['ii_ids'][$row['data']['banner_image']] = 0;
				if($row['data']['key_art_image']){
					foreach($row['data']['key_art_image'] as $key_art_image_id){
						$media_ids['ii_ids'][$key_art_image_id] = 0;
					}
				}
				break;
			case 'Personage':
				if($row['data']['head_image'])      $media_ids['ii_ids'][$row['data']['head_image']]      = 0;
				if($row['data']['full_body_image']) $media_ids['ii_ids'][$row['data']['full_body_image']] = 0;
				break;
			}
		}
		$media_ids['ii_ids'] = CommonUtils::getFolderTypeByIiId($dbHandle,$media_ids['ii_ids'],$premium);
		return $media_ids;
	}
	/**
	 * Get db3 data from change_log
	 */
	public function getDb3DataFromChangeLog($dbHandle, &$change_log, $premium=false){/*{{{*/
		$data   = $del = array();
		$c_data = array(); # for the cache
		$getter = new Processor();

		foreach($change_log as $row){
			if($row['is_active']){
				switch($row['type']){  # UPDATE ITEMS /*{{{*/
				case 'chapter':
				case 'chapter-language':
				case 'chapter-tvbcom_category':
					$id = isset($row['keys']['id']) ? $row['keys']['id'] : $row['keys']['chapter_id'];
					if(empty($c_data['Chapter'][$id])){
						$data[] = array('type' => 'Chapter', 'data'=>$getter->getChapterForPublish($id));
						$c_data['Chapter'][$id] = true;
					}
					break;
				case 'episode':
				case 'episode-language':
				#case 'episode-video':
					$id = isset($row['keys']['id']) ? $row['keys']['id'] : $row['keys']['episode_id'];
					if(empty($c_data['Episode'][$id])){
						$data[] = array('type' => 'Episode', 'data'=>$getter->getEpisodeForPublish($id));
						$c_data['Episode'][$id] = true;
					}
					break;
				case 'tag':
					## 
					break;
				case 'cast':
				case 'cast-language':
				#case 'cast_dictionary':
					$id = isset($row['keys']['id']) ? $row['keys']['id'] : $row['keys']['cast_id'];
					if(empty($c_data['Personage'][$id])){
						$data[] = array('type' => 'Personage', 'data'=>$getter->getCastForPublish($id));
						$c_data['Personage'][$id] = true;
					}
					break;
				case 'info_address':
				case 'info_award':
				case 'info_biography':
				case 'info_general_information':
				case 'info_product':
				#case 'info_pageant': # Unused
				case 'info_q_a':
				case 'info_recipe':
				case 'info_song':
					$id  = $row['keys']['id'];
					if(empty($c_data[$row['type']][$id])){
						$fun = ucfirst(substr($row['type'],5));
						if($fun=='General_information') $fun = 'General';
						if($fun=='Q_a') $fun = 'QA';
						$fun = 'getInfo'.$fun.'ForPublish';

						$data[] = array('type'=>'Info', 'data'=>$getter->$fun($row['keys']['id']));
						$c_data[$row['type']][$id] = true;
					}
					break;
				case 'video':
				case 'video-language':
				case 'video_export':
				case 'video_ppv':
				case 'video_premium':
				case 'video_subscription':
					if('video_export' == $row['type']){
						if($premium){
							$_export = CommonUtils::exec_sql($dbHandle,'select video_id from p_video_export where id=?',array($row['keys']['id']));
						}else{
							$_export = CommonUtils::exec_sql($dbHandle,'select video_id from   video_export where id=?',array($row['keys']['id']));
						}
						$id = $_export[0]['video_id'];
					}else{
						$id = isset($row['keys']['id']) ? $row['keys']['id'] : $row['keys']['video_id'];
					}
					if(empty($c_data['Video'][$id])){
						$video_data = $getter->getVideoForPublish($id);
						if(!$video_data) break; // The video not in folder

						$data[]     = array('type'=>'Video', 'data'=>$video_data);

						foreach(CommonUtils::getFoldersByItemId($dbHandle, $id, $premium, true) as $folder_id){
							$item_data = PDESGetFolderItemData($folder_id,$id);
							$data[] = array(
								'type'=>'FolderItemVideo',
								'data'=>$getter->genFolderItemVideoDataByFolderItemDataAndVideoData($item_data,$video_data)
							);
						}

						if(!self::inChangeLog($change_log,'programme')){// because them has folders field.
							if($premium){
								$_video_obj = CommonUtils::exec_sql($dbHandle,'select programme_id from p_video where id=?',array($id));
							}else{
								$_video_obj = CommonUtils::exec_sql($dbHandle,'select programme_id from video where id=?',array($id));
							}
							$_p_id = $_video_obj[0]['programme_id'];
							$_p_= $getter->getProgrammeForPublish($_p_id);
							if(!$_p_){
								return array('update'=>array(),'delete'=>array(array('type'=>'Programme','keys'=>array('id'=>$_p_id))));
							}
							$data[] = array('type'=>'Programme', 'data'=>$_p_);
						}
						$c_data['Video'][$id] = true;
					}
					break;
				case 'image':
				case 'image-language':
				#case 'image_folder-config':
					$id = isset($row['keys']['id']) ? $row['keys']['id'] : $row['keys']['image_id'];
					if(empty($c_data['Image'][$id])){
						$image_data = $getter->getImageForPublish($id,'folder_type no used');
						if(!$image_data) break; // The image not in folder

						$data[]     = array( 'type'=>'Image', 'data'=>$image_data);

						$all_folder = CommonUtils::getFoldersByItemId($dbHandle, $id, $premium, false);
						foreach($all_folder as $folder_id){
							$item_data = PDESGetFolderItemData($folder_id,$id);
							$data[] = array(
								'type'=>'FolderItemImage',
								'data'=>$getter->genFolderItemImageDataByFolderItemDataAndImageData($item_data,$image_data)
							);
						}

						if(!self::inChangeLog($change_log,array('programme','episode','cast'))){// because them has folders field.
							#error_log(" has some folders:".print_r($all_folder,1));
							foreach($all_folder as $folder_id){
								$rs = PDESGetPECIdsByFolderId($folder_id);
								#error_log(" has ids:".print_r($rs,1));
								foreach($rs as $r){
									switch($r['type']){
									case 'p': 
										$_p_= $getter->getProgrammeForPublish($r['id']);
										if(!$_p_){
											return array('update'=>array(),'delete'=>array(array('type'=>'Programme','keys'=>array('id'=>$r['id']))));
										}
										$data[] = array('type'=>'Programme', 'data'=>$_p_);
										break;
									case 'e': 
										$data[] = array('type'=>'Episode', 'data'=>$getter->getEpisodeForPublish($r['id']));
										break;
									case 'c': 
										$data[] = array('type'=>'Personage', 'data'=>$getter->getCastForPublish($r['id']));
										break;
									}
								}
							}
						}
						$c_data['Image'][$id] = true;
					}
					break;
				case 'programme-tvbcom_category':
					$p_id = $row['keys']['programme_id'];
					if(empty($c_data['PCC'][$p_id])){
						$items = $getter->getProgrammeCategoriesForPublish($p_id);
						foreach($items as $item){
							$data[] = array('type'=>'ProgrammeCategory','data'=>$item);
						}

						$items = $getter->getProgrammeChannelsForPublish($p_id);
						foreach($items as $item){
							$data[] = array('type'=>'ProgrammeChannel','data'=>$item);
						}
						$c_data['PCC'][$p_id] = true;
					}
					break;
				case 'programme':
				case 'programme-language':
				case 'programme_cpl':
				case 'programme_ppv':
				case 'programme_premium':
				case 'programme_subscription':
					$id = isset($row['keys']['id']) ? $row['keys']['id'] : $row['keys']['programme_id'];
					if(empty($c_data['Programme'][$id])){
						$_p_= $getter->getProgrammeForPublish($id);
						if(!$_p_){
							return array('update'=>array(),'delete'=>array(array('type'=>'Programme','keys'=>array('id'=>$id))));
						}
						$data[] = array('type'=>'Programme','data'=>$_p_);
						$c_data['Programme'][$id] = true;
					}
					break;
				case 'folder':
				case 'folder-language':
					$id = isset($row['keys']['id']) ? $row['keys']['id'] : $row['keys']['folder_id'];
					if(empty($c_data['Folder'][$id])){
						# for bug 7281
						$_folder_data = PDESGetFolderData($id);
						if($_folder_data){
							$data[] = array('type'=>'Folder','data'=>PDESGetFolderData($id));
						}
						$c_data['Folder'][$id] = true;
					}
					break;
				case 'folder_item':
				case 'folder_item-language':
					$folder_id = $row['keys']['folder_id'];
					if(empty($c_data['Folder'][$folder_id])){
						# for bug 7281
						$_folder_data = PDESGetFolderData($folder_id);
						if($_folder_data){
							$data[] = array('type'=>'Folder','data'=>PDESGetFolderData($folder_id));
						}
						$c_data['Folder'][$folder_id] = true;
					}
					$_key = $row['keys']['folder_id'].$row['keys']['item_id'];
					if(empty($c_data['FolderItem'][$_key])){
						$_folder_item_data = PDESGetFolderItemData($row['keys']['folder_id'],$row['keys']['item_id']);
						$data[] = array('type'=>'FolderItem', 'data'=>$_folder_item_data);
						$c_data['FolderItem'][$_key] = true;

						# 如果 folder_item 被修改，service db 的 folder_item-image & folder_item-video 也要更新
						$_media_id = $row['keys']['item_id'];
						if($_folder_item_data['item_type']==1){      // is video  
							$in_change_log =  CommonUtils::inChangeLog($change_log, 'video', array('id'=>$_media_id));
							if($in_change_log) break; // 有在 change_log 无需在此设置

							$_video_data = $getter->getVideoForPublish($_media_id);
							if(!$_video_data) break; // The video not in folder

							$data[] = array('type'=>'Video', 'data'=>$_video_data);
							$data[] = array(
								'type'=>'FolderItemVideo',
								'data'=>$getter->genFolderItemVideoDataByFolderItemDataAndVideoData($_folder_item_data,$_video_data)
							);
						}
						else if($_folder_item_data['item_type']==2) // is image
						{
							$in_change_log =  CommonUtils::inChangeLog($change_log, 'image', array('id'=>$_media_id));
							if($in_change_log) break; // 有在 change_log 无需在此设置

							$_image_data = $getter->getImageForPublish($row['keys']['item_id'],'folder_type no used');
							if(!$_image_data) break; // The image not in folder

							$data[] = array('type'=>'Image', 'data'=>$_image_data);
							$data[] = array(
								'type'=>'FolderItemImage',
								'data'=>$getter->genFolderItemImageDataByFolderItemDataAndImageData($_folder_item_data,$_image_data)
							);
						}
					}
					break;
				}/*}}}*/
			}else{
				switch($row['type']){  # DETETE ITEMS   /*{{{*/
				case 'chapter':
				case 'chapter-language':
					$id = isset($row['keys']['id']) ? $row['keys']['id'] : $row['keys']['chapter_id'];
					$del["Chapter:$id"] = array('type'=>'Chapter','keys'=>array('id'=>$id));
					break;
				case 'chapter-tvbcom_category': # Don't delete it, just update
					$id = $row['keys']['chapter_id'];
					if(empty($c_data['Chapter'][$id])){
						$data[] = array('type' => 'Chapter', 'data'=>$getter->getChapterForPublish($id));
						$c_data['Chapter'][$id] = true;
					}
					break;
				case 'episode':
				case 'episode-language':
					$id = isset($row['keys']['id']) ? $row['keys']['id'] : $row['keys']['episode_id'];
					$del["Episode:$id"] = array('type'=>'Episode','keys'=>$row['keys']);
					break;
				#case 'episode-video': # Don't delete it, just update
				#	$id = $row['keys']['episode_id'];
				#	if(empty($c_data['Episode'][$id])){
				#		$data[] = array('type' => 'Episode', 'data'=>$getter->getEpisodeForPublish($id));
				#		$c_data['Episode'][$id] = true;
				#	}
				#	break;
				case 'cast':
				case 'cast-language':
				#case 'cast_dictionary':
					$id = isset($row['keys']['id']) ? $row['keys']['id'] : $row['keys']['cast_id'];
					$del["Personage:$id"] = array('type'=>'Personage','keys'=>array('id'=>$id));
					break;
				case 'info_address':
				case 'info_award':
				case 'info_biography':
				case 'info_general_information':
				case 'info_product':
				case 'info_q_a':
				case 'info_recipe':
				case 'info_song':
					$id   = $row['keys']['id'];
					$type = 'INFO_TYPE_'.strtoupper(substr($row['type'],5));
					$type = constant("Processor::$type");
					$del["Info:$id:$type"] = array('type'=>'Info','keys'=>array('info_id'=>$id,'info_type_id'=>$type));
					break;
				case 'video':
				case 'video-language':
					$id = isset($row['keys']['id']) ? $row['keys']['id'] : $row['keys']['video_id'];
					$del["Video:$id"] = array('type'=>'Video','keys'=>array('id'=>$id));
					break;
				case 'video_export':
				case 'video_ppv':
				case 'video_premium':
				case 'video_subscription':
					# Don't delete it, just update
					$id = isset($row['keys']['id']) ? $row['keys']['id'] : $row['keys']['video_id'];
					if(empty($c_data['Video'][$id])){
						$video_data = $getter->getVideoForPublish($id);
						if(!$video_data) break; // The video not in folder
						$data[]     = array('type'=>'Video', 'data'=>$video_data);

						foreach(CommonUtils::getFoldersByItemId($dbHandle, $id, $premium, true) as $folder_id){
							$item_data = PDESGetFolderItemData($folder_id,$id);
							$data[] = array(
								'type'=>'FolderItemVideo',
								'data'=>$getter->genFolderItemVideoDataByFolderItemDataAndVideoData($item_data,$video_data)
							);
						}

						if(!self::inChangeLog($change_log,'programme')){// because them has folders field.
							if($premium){
								$_video_obj = CommonUtils::exec_sql($dbHandle,'select programme_id from p_video where id=?',array($id));
							}else{
								$_video_obj = CommonUtils::exec_sql($dbHandle,'select programme_id from video where id=?',array($id));
							}
							$_p_id = $_video_obj[0]['programme_id'];
							$_p_= $getter->getProgrammeForPublish($_p_id);
							if(!$_p_){
								return array('update'=>array(),'delete'=>array(array('type'=>'Programme','keys'=>array('id'=>$_p_id))));
							}
							$data[] = array('type'=>'Programme','data'=>$_p_);
						}
						$c_data['Video'][$id] = true;
					}
					break;
				case 'image':
				case 'image-language':
					#case 'image_folder-config':
					$id = isset($row['keys']['id']) ? $row['keys']['id'] : $row['keys']['image_id'];
					$del["Image:$id"] = array('type'=>'Image','keys'=>array('id'=>$id));
					break;
				case 'programme':
				case 'programme-language':
					$id = isset($row['keys']['id']) ? $row['keys']['id'] : $row['keys']['programme_id'];
					$del["Programme:$id"] = array('type'=>'Programme','keys'=>array('id'=>$id));
					break;
				case 'programme_cpl':
				case 'programme_ppv':
				case 'programme_premium':
				case 'programme_subscription':
				case 'programme-tvbcom_category': # Don't delete it, just update
					$id = isset($row['keys']['id']) ? $row['keys']['id'] : $row['keys']['programme_id'];
					if(empty($c_data['Programme'][$id])){
						$_p_= $getter->getProgrammeForPublish($id);
						if(!$_p_){
							return array('update'=>array(),'delete'=>array(array('type'=>'Programme','keys'=>array('id'=>$id))));
						}
						$data[] = array('type'=>'Programme','data'=>$_p_);
						$c_data['Programme'][$id] = true;
					}
					break;
				case 'folder':
				case 'folder-language':
					$id = isset($row['keys']['id']) ? $row['keys']['id'] : $row['keys']['folder_id'];
					$del["Folder:$id"] = array('type'=>'Folder','keys'=>array('id'=>$id));
					break;
				case 'folder_item':
				case 'folder_item-language':
					$_key = implode(':',$row['keys']);
					$_fid = $row['keys']['folder_id'];
					$item_types = $getter->getFolderItemTypes();

					if($premium){
						$item_type_data = CommonUtils::exec_sql($dbHandle,'select * from p_folder where id=?',array($_fid));
					}else{
						$item_type_data = CommonUtils::exec_sql($dbHandle,'select * from folder where id=?',array($_fid));
					}

					if(empty($item_type_data)) break; //folder not exists

					if($item_type_data[0]['folder_item_type_id']==AC::FOLDER_TYPE_IMAGE){
						$item_type = $item_types['image'];
					}else{
						$item_type = $item_types['video'];
					}

					$del["FolderItem:$_key"] = array(
						'type'=>'FolderItem',
						'keys'=>array(
							'item_id'=>$row['keys']['item_id'],
							'folder_id'=>$_fid,
							'item_type'=>$item_type
						)
					);
					break;
				}/*}}}*/
			}
		}

		reset($change_log);

		return array(
			'delete'=>CommonUtils::sortDb3Data($del,true),
			'update'=>CommonUtils::sortDb3Data($data)
		);
	}/*}}}*/
	/**
	 * sort db3 data
	 */
	private function sortDb3Data(&$data,$reverse=false){
		if(!$data) return array();
		$sort = array(
			'Category',
			'Programme',
			'ProgrammeCategory',
			'ProgrammeChannel',
			'Episode',
			'Personage',
			'Info',
			'Image',
			'Video',
			'Chapter',
			'Folder',
			'FolderItem',
			'FolderItemImage',
			'FolderItemVideo',
		);

		if($reverse) $sort = array_reverse($sort);

		$new_data = array_fill_keys($sort,array());
		foreach($data as $row){
			$new_data[$row['type']][] = $row;
		}
		return call_user_func_array('array_merge',array_filter($new_data));
	}

	/** 
	 * Get db3 data from old flow
	 */
	public function getDb3Data($programme_id,$operationUser){/*{{{*/
		$obj = new Processor();
		return  $obj->publishCompleteProgramme($programme_id,$operationUser);
	}/*}}}*/

	/**
	 * Get all video vi_id from dataArray
	 * for new proofread flow
	 * @author vanni
	 * @since modified at 2011-01-12
	 */
	public function getAllMediaId($dbHandle,$programme_id,$premium=false){/*{{{*/
		$media_ids = CommonUtils::getProgrammeMediaIds($dbHandle,$programme_id,$premium);
		$media_ids['ii_ids'] = CommonUtils::getFolderTypeByIiId($dbHandle,$media_ids['ii_ids'],$premium);
		return $media_ids;
	}/*}}}*/

	/**
	 * Get Folders By Item IDs
	 * @return array
	 */
	public function getFoldersByItemId($dbHandle, $item_id,$is_premium=false,$is_video=false){/*{{{*/
		$item_type_id = $is_video ? AC::FOLDER_TYPE_VIDEO : AC::FOLDER_TYPE_IMAGE;
		$prefix       = $is_premium ? 'p_'  : '';
		$table_name   = $is_video ? ($prefix.'video') : ($prefix.'image');
		if(!is_array($item_id)){
			$item_id = array_unique(array_filter(preg_split('/\D+/',$item_id)));
		}else{
			$item_id = array_unique(array_filter($item_id,'is_numeric'));
		}
		$item_id = implode(',',$item_id);
		if(empty($item_id)) return array();

		$sql = "
			select distinct f.id from {$prefix}folder f,{$prefix}folder_item fi,$table_name m
			where f.id=fi.folder_id and f.folder_item_type_id=? and fi.item_id in($item_id) and m.id=fi.item_id and m.status=?
		";
		$folders = CommonUtils::exec_sql($dbHandle, $sql, array($item_type_id, AC::STATUS_NEW));
		$rs = array();
		foreach($folders as $r) $rs[] = $r['id'];
		return $rs;
	}/*}}}*/

	/**
	 * Get Items By Folders
	 * @return array
	 */
	public function getItemsByFolders($dbHandle, $folder_id, $is_premium=false,$is_video=false){
		$item_type_id = $is_video ? AC::FOLDER_TYPE_VIDEO : AC::FOLDER_TYPE_IMAGE;
		$prefix       = $is_premium ? 'p_'  : '';
		$table_name   = $is_video ? ($prefix.'video') : ($prefix.'image');
		if(!is_array($folder_id)){
			$folder_id = array_unique(array_filter(preg_split('/\D+/',$folder_id)));
		}else{
			$folder_id = array_unique(array_filter($folder_id,'is_numeric'));
		}
		$folder_id = implode(',',$folder_id);
		if(empty($folder_id)) return array();

		$sql = "
			select distinct m.id from {$prefix}folder f,{$prefix}folder_item fi,$table_name m
			where f.id=fi.folder_id and f.folder_item_type_id=? and f.id in($folder_id) and m.id=fi.item_id and m.status=?
		";
		$folders = CommonUtils::exec_sql($dbHandle, $sql, array($item_type_id, AC::STATUS_NEW));
		$rs = array();
		foreach($folders as $r) $rs[] = $r['id'];
		return $rs;
	}

	/**
	 * Check change log by tablename
	 * @return boolean
	 */
	public function inChangeLog(& $change_log, $table, $keys=array()){/*{{{*/
		$table = is_array($table) ? $table : array($table);
		foreach($change_log as $row){
			if(in_array($row['type'], $table)){
				if($keys){
					$true = true;
					foreach($keys as $key=>$val){
						if(!isset($row['keys'][$key]) || $row['keys'][$key] != $val){
							$true = false;
							break;
						}
					}
					if($true) return true;
				}else{
					return true;
				}
			}
		}
		return false;
	}/*}}}*/

	/**
	 * get Mongodb obj
	 * @return Mongo
	 */
	public static function getMongoDB(){/*{{{*/
		$config  = ConfigReaderFactory::getInstance()->getConfigReader(AC::CONFIG_FILE)->getConfig();
		$linkurl = (string)$config->mongodb;
		$connect = new Mongo($linkurl,array("persist" => "x"));
		return $connect->pdes->change_log;
	}/*}}}*/


	/**
	 * get episode change_log from dataArray
	 */
	public function getEpisodeChangeLogFromDataArray(&$data){
		$change_log = array();
		$episode_tables = array(
			'episode'                   => array('id'),
			'episode-language'          => array('episode_id','language_id'),
			'tag'                       => array('id'),
			'folder'                    => array('id'),
			'folder-language'           => array('folder_id','language_id'),
			'folder_item'               => array('folder_id','item_id'),
			'folder_item-language'      => array('folder_id','item_id','language_id'),
			'image'                     => array('id'),
			'image-language'            => array('image_id','language_id'),
			'image_folder-config'       => array('folder_id'),
			'info_address'              => array('id'),
			'info_award'                => array('id'),
			'info_biography'            => array('id'),
			'info_general_information'  => array('id'),
			'info_pageant'				=> array('id'),
			'info_product'              => array('id'),
			'info_q_a'                  => array('id'),
			'info_recipe'               => array('id'),
			'info_song'                 => array('id'),
			'cast'                      => array('id'),
			'cast-language'             => array('cast_id','language_id'),
            'cast_dictionary'           => array('id'),
		);
		$template = array(
			'is_active'    => 1,
			'is_publish'   => 0,
			'programme_id' => 0,
			'episode_id'   => $data['episode'][0]['id']
		);
		foreach($data as $table=>&$rows){
			if($rows) foreach($rows as &$row){
				$template['type'] = $table;
				$template['keys'] = array();
				foreach($episode_tables[$table] as $key){
					$template['keys'][$key] = $row[$key];
				}
				$change_log[] = $template;
			}
		}
		return $change_log;
	}
}
